package ar.edu.caece.pl.asin.model.impl;

import ar.edu.caece.pl.alex.model.IToken;
import ar.edu.caece.pl.alex.model.impl.Token;
import ar.edu.caece.pl.asin.manager.IAnalizadorSintactico;
import ar.edu.caece.pl.asin.manager.impl.AbstractAnalizadorSintactico;
import ar.edu.caece.pl.asin.model.ITokenStream;

public class Condicion extends AbstractAnalizadorSintactico implements IAnalizadorSintactico {
	
	/* INICIALIZACION */	
	public Condicion ( ITokenStream ts ) {
		super(ts, false);
	}
	public Condicion ( ITokenStream ts, boolean debugMode ) {
		super(ts,debugMode);
	}
	
	
	/** 
	 * Devuelve true si reconoce una condicion del tipo expresion operador expresion, o even() y odd()
	 */
	public boolean reconocer () {

		boolean recognized = true; //(asumimos correctitud hasta demostrar lo contrario)
		
		//----------------------------------------------
		//Agrego info de debug de la produccion
		em.debug( "Reconocer Condicion:", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
		//----------------------------------------------
		
		/* <CONDICION> -> ODD(<EXP>) |
						  EVEN(<EXP>) |
						  <EXP> <C'> <EXP>*/
		
		if ( this.getTokenSiguiente().equals( new Token (IToken.PALABRA_RESERVADA_ODD) ) ) {
			
			// <CONDICION> -> ODD(<EXP>)
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<CONDICION> -> ODD(<EXP>", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------
			
			if( !this.reconocerToken(IToken.PALABRA_RESERVADA_ODD) ) {
				return false;
			}
			
			if( !this.reconocerToken(IToken.TYPE_PARENTESIS_IZQ) ) {
				return false;
			}
			
			// Reconocer Expresion
			IAnalizadorSintactico expresion = new Expresion(this.tokenStream,this.debugMode);
			recognized &= expresion.reconocer();
			
			if( !this.reconocerToken(IToken.TYPE_PARENTESIS_DER) ) {
				return false;
			}
		
		} else if ( this.getTokenSiguiente().equals( new Token (IToken.PALABRA_RESERVADA_EVEN) ) ) {	
			
			// <CONDICION> -> EVEN(<EXP>)
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<CONDICION> -> EVEN(<EXP>)", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------
			
			if( !this.reconocerToken(IToken.PALABRA_RESERVADA_EVEN) ) {
				return false;
			}
			
			if( !this.reconocerToken(IToken.TYPE_PARENTESIS_IZQ) ) {
				return false;
			}
			
			// Reconocer Expresion
			IAnalizadorSintactico expresion = new Expresion(this.tokenStream,this.debugMode);
			recognized &= expresion.reconocer();
			
			if( !this.reconocerToken(IToken.TYPE_PARENTESIS_DER) ) {
				return false;
			}
		
		} else if ( Expresion.primeros(this.getTokenSiguiente()) ){	
			
			// <CONDICION> -> <EXP> <C'> <EXP>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<CONDICION> -> <EXP> <C'> <EXP>", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------
			
			// Reconocer Expresion
			IAnalizadorSintactico expresion = new Expresion(this.tokenStream,this.debugMode);
			recognized &= expresion.reconocer();
			
			// Reconocer C'
			IAnalizadorSintactico c1 = new C1(this.tokenStream,this.debugMode);
			recognized &= c1.reconocer();
			
			// Reconocer Expresion
			IAnalizadorSintactico expresion2 = new Expresion(this.tokenStream,this.debugMode);
			recognized &= expresion2.reconocer();
		
		} else {
			
			//No deberia darse el caso, pero si se llama a reconocer() en un estado incorrecto deberia salir por aqui
			em.error("Se esperaba " + IToken.PALABRA_RESERVADA_ODD +
					" o " + IToken.PALABRA_RESERVADA_EVEN +
					" o expresion", this.getTokenSiguiente());
			
			//Tratamiento de errores
			em.recover(this.getClass(), this.tokenStream);
			
			return false;
		}
		
		return recognized;
	}
	
	public static boolean primeros(IToken token) {
		return  token.equals( new Token(IToken.PALABRA_RESERVADA_ODD) ) ||
				token.equals( new Token(IToken.PALABRA_RESERVADA_EVEN) ) ||
				Expresion.primeros(token);
	}
}
